package com.mlink.ai.chat.ui.activity

import android.annotation.SuppressLint
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.widget.Toast
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.flexbox.FlexboxLayoutManager
import com.mlink.ai.chat.assistant.robot.R
import com.mlink.ai.chat.assistant.robot.databinding.ActivityFeedbackBinding
import com.mlink.ai.chat.ui.adapter.FeedbackCategoryRecyclerAdapter
import com.mlink.ai.chat.ui.adapter.FeedbackPhotoRecyclerAdapter
import com.mlink.ai.chat.ui.viewmodel.FeedbackViewModel
import com.mlink.ai.chat.utils.FileUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream

class FeedbackActivity : BaseActivity<ActivityFeedbackBinding>() {

    private lateinit var categoryAdapter: FeedbackCategoryRecyclerAdapter
    private lateinit var photoAdapter: FeedbackPhotoRecyclerAdapter
    private val viewModel: FeedbackViewModel by viewModels()

    private var loadingDialog: AlertDialog? = null

    override fun getViewBinding(): ActivityFeedbackBinding {
        return ActivityFeedbackBinding.inflate(layoutInflater)
    }

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    override fun initViews() {
        binding.backIv.setOnClickListener {
            finish()
        }
        viewModel.isSuccess.observe(this) {
            if (loadingDialog?.isShowing == true) {
                loadingDialog?.dismiss()
            }
            if (it) {
                Toast.makeText(this, R.string.feedback_submit_success, Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(this, R.string.feedback_submit_fail, Toast.LENGTH_LONG).show()
            }
        }

        binding.flSubmit.setOnClickListener {
            if (binding.etDetail.text.trim().length < 10) {
                binding.etDetail.setBackgroundResource(R.drawable.shape_bg_feedback_edit_empty)
                binding.scrollView.scrollTo(0, binding.titleMoreDetail.y.toInt())
                binding.etDetail.requestFocus()
                binding.tvDetailError.visibility = View.VISIBLE
                return@setOnClickListener
            }
            if (binding.etEmail.text.isEmpty()) {
                binding.etEmail.setBackgroundResource(R.drawable.shape_bg_feedback_edit_empty)
                binding.scrollView.scrollTo(0, binding.titleAddEmail.y.toInt())
                binding.etEmail.requestFocus()
                binding.tvEmailError.text = resources.getText(R.string.feedback_email_empty)
                binding.tvEmailError.visibility = View.VISIBLE
                return@setOnClickListener
            }
            if (!isValidEmail(binding.etEmail.text.toString())) {
                binding.etEmail.setBackgroundResource(R.drawable.shape_bg_feedback_edit_empty)
                binding.scrollView.scrollTo(0, binding.titleAddEmail.y.toInt())
                binding.etEmail.requestFocus()
                binding.tvEmailError.text = resources.getText(R.string.feedback_incorrect_email)
                binding.tvEmailError.visibility = View.VISIBLE
                return@setOnClickListener
            }
            showLoadingDialog()
            lifecycleScope.launch(Dispatchers.IO) {
                runCatching {
                    val fileList = getAllFile()
                    if (fileList.isNotEmpty()) {
                        viewModel.feedbackWithFile(
                            this@FeedbackActivity,
                            categoryAdapter.selectedData,
                            binding.etDetail.text.toString(),
                            fileList,
                            binding.etEmail.text.toString()
                        )
                    } else {
                        viewModel.feedback(
                            this@FeedbackActivity,
                            categoryAdapter.selectedData,
                            binding.etDetail.text.toString(),
                            binding.etEmail.text.toString(),
                            emptyList()
                        )
                    }
                }.onFailure {
                    withContext(Dispatchers.Main) {
                        if (loadingDialog?.isShowing == true) {
                            loadingDialog?.dismiss()
                        }
                    }
                }
            }

        }

        binding.etDetail.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) =
                Unit

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit

            override fun afterTextChanged(s: Editable?) {
                if (binding.etDetail.text.trim().length >= 10) {
                    binding.etDetail.setBackgroundResource(R.drawable.shape_bg_prompt_create_text_normal)
                    binding.tvDetailError.visibility = View.INVISIBLE
                }

            }
        })

        binding.etEmail.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) =
                Unit

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit

            override fun afterTextChanged(s: Editable?) {
                if (binding.etEmail.text.isNotEmpty()) {
                    binding.etEmail.setBackgroundResource(R.drawable.shape_bg_prompt_create_text_normal)
                    binding.tvEmailError.visibility = View.INVISIBLE
                }
            }
        })

        initCategoryRecycler()
        initAddPhotoRecycler()
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (resultCode != Activity.RESULT_OK || data == null) return super.onActivityResult(
            requestCode,
            resultCode,
            data
        )
        if (requestCode == CODE_REQUEST_PHOTO) {
            if (data.data != null) {
                val uri = data.data!!
                photoAdapter.data.add(photoAdapter.data.size - 1, uri.toString())
                photoAdapter.notifyDataSetChanged()
            } else {
                val clipData = data.clipData
                clipData ?: return
                for (i in 0 until clipData.itemCount) {
                    val uri = clipData.getItemAt(i).uri
                    photoAdapter.data.add(photoAdapter.data.size - 1, uri.toString())
                }
                photoAdapter.notifyDataSetChanged()
            }
        }

        return super.onActivityResult(requestCode, resultCode, data)
    }

    private fun initCategoryRecycler() {
        categoryAdapter = FeedbackCategoryRecyclerAdapter()
        categoryAdapter.data.run {
            add(getString(R.string.feedback_category_refund))
            add(getString(R.string.feedback_category_cancel_subscription))
            add(getString(R.string.feedback_category_bug))
            add(getString(R.string.feedback_category_love_it))
            add(getString(R.string.feedback_category_others))
        }
        binding.recyclerChoose.run {
            layoutManager = FlexboxLayoutManager(this@FeedbackActivity)
            adapter = this@FeedbackActivity.categoryAdapter
        }
    }

    private fun initAddPhotoRecycler() {
        photoAdapter = FeedbackPhotoRecyclerAdapter()
        photoAdapter.run {
            data.add("#")
            onSelectPhoto = {
                val intent = Intent(Intent.ACTION_PICK)
                intent.type = "*/*"
                val types = arrayOf("image/*", "video/*")
                intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
                intent.putExtra(Intent.EXTRA_MIME_TYPES, types)
                try {
                    startActivityForResult(intent, CODE_REQUEST_PHOTO)
                } catch (e: ActivityNotFoundException) {
                    // do nothing now
                }
            }
        }
        binding.rvAddPhoto.run {
            layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
            adapter = photoAdapter
        }
    }

    private fun getAllFile(): List<File> {
        val data = mutableListOf<String>().apply {
            addAll(photoAdapter.data)
        }
        data.remove("#")
        val result = mutableListOf<File>()
        val dir = File(FileUtils.getCacheDir(this), "feedback")
        if (dir.exists()) {
            dir.listFiles()?.forEach {
                it.delete()
            }
        } else {
            dir.mkdirs()
        }
        uriLoop@ for (uri in data) {
            val input = contentResolver?.openInputStream(Uri.parse(uri))
            input ?: continue@uriLoop

            val file = File(dir, FileUtils.getFileName(this, Uri.parse(uri)))

            if (!file.exists()) {
                file.createNewFile()
            }
            try {
                FileOutputStream(file).use { outputStream ->
                    val buffer = ByteArray(1024)
                    var length: Int
                    while (input.read(buffer).also { length = it } > 0) {
                        outputStream.write(buffer, 0, length)
                    }
                }
            } finally {
                input.close()
            }
            result.add(file)
        }
        return result
    }

    private fun showLoadingDialog() {
        if (loadingDialog == null) {
            loadingDialog =
                AlertDialog.Builder(
                    this,
                    R.style.CustomAlertDialogStyle
                ).setView(
                    LayoutInflater.from(this).inflate(R.layout.loading, binding.root, false)
                )
                    .create()
            loadingDialog!!.setCancelable(false)
            loadingDialog!!.setOnKeyListener { _, keyCode, keyEvent ->
                if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == KeyEvent.ACTION_UP) {
                    loadingDialog!!.dismiss()
                    finish()
                    true
                } else {
                    false
                }
            }
        }
        loadingDialog?.show()
    }

    private fun isValidEmail(email: String): Boolean {
        val pattern = Regex("^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}\$")
        return pattern.matches(email)
    }

    companion object {
        private const val CODE_REQUEST_PHOTO = 101
    }

}